﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using DoeLibsMVC.Security;
using DoeLibsMVC.Models;
using DoeObjects;

namespace DoeLibsMVC.Controllers
{
    public class AuthentificationController : BaseController
    {
        [HttpGet]
        public ActionResult Login()
        {
            if (this.User != null && this.User.Identity.IsAuthenticated == true)
            {
                return RedirectToAction("AccessDenied");
            }
            else
            {
                return View();
            }
        }

        [HttpPost]
        public ActionResult Login(LoginModel model)
        {
            if (ModelState.IsValid)
            {
				SecurityHelper.LoginStatus status = SecurityHelper.login(model.EMail, model.Password);

				if (status == SecurityHelper.LoginStatus.OK)
                    return RedirectToAction("MyBorrowings", "User");
				else if (status == SecurityHelper.LoginStatus.ACCOUNT_NOT_ACTIVATED)
				{
					ModelState.AddModelError("EMail", "Account is still waiting for activation");
					return View(model);
				}
				else if (status == SecurityHelper.LoginStatus.WRONG_PASSWORD
					|| status == SecurityHelper.LoginStatus.UNKNOWN_USERNAME)
				{
					ModelState.AddModelError("EMail", "Incorrect email and/or password");
					return View(model);
				}
				else// if (status == SecurityHelper.LoginStatus.ACCOUNT_HAS_EXPIRED) // last option available
				{
					ModelState.AddModelError("EMail", "Account has expired");
					return View(model);
				}
            }
            return View(model); // Will never reach here but error if excluded ...
        }

        public ActionResult Logout()
        {
            FormsAuthentication.SignOut();
            System.Web.HttpContext.Current.User = null;

            base.Message = new HttpMessage("You have been logged out", true);

            return RedirectToAction("Index", "Home");
        }

        public ActionResult AccessDenied()
        {
            Response.Clear();
            return new HttpStatusCodeResult(403);
        }

		[HttpGet]
		public ActionResult Register()
		{
			return View(new RegisterModel());
		}

		[HttpPost]
		public ActionResult Register(RegisterModel model)
		{
            if (model.Password != model.ConfirmPassword)
            {
                ModelState.AddModelError("ConfirmPassword", "The passwords don't match");
            }

            if (string.IsNullOrEmpty(model.EMail) || DoeObjects.User.getUserByMail(model.EMail) != null)
            {
                ModelState.AddModelError("EMail", "E-Mail already in use");
            }

            if (model.CategoryId == 1 && string.IsNullOrEmpty(model.Room))
            {
                ModelState.AddModelError("Room", "Room required for Staff members");
            }

            if (model.CategoryId == 1 && string.IsNullOrEmpty(model.UniPhone))
            {
                ModelState.AddModelError("UniPhone", "Uniphone required for Staff members");
            }

			if (ModelState.IsValid)
			{
                User user = new User();
                user.FirstName = model.FirstName;
                user.LastName = model.LastName;
                user.Salt = SecurityHelper.generateSalt();
                user.Password = SecurityHelper.secureString(user.Salt + model.Password);
                user.EMail = model.EMail;
                user.Category = UserCategory.getById(model.CategoryId);
                user.Acceptor = DoeObjects.User.getUserByUserId(model.AcceptorId);
                
                //fields which are only for staff members:
                user.UniPhone = (model.CategoryId == 1) ? model.UniPhone : null; 
                user.Room = (model.CategoryId == 1) ? model.Room : null;


                Notification notification = new Notification();
                notification.Recipient = user.Acceptor;
                notification.Sender = user;
                notification.Message = string.Format("{0} {1} ({2}) asks of you to activate his account as a {3} member", user.FirstName, user.LastName, user.EMail, user.Category.Name);
                notification.Type = NotificationType.REGISTRATION_ACCEPT_REQUEST;

                if (user.save() && notification.save())
                {
                    base.Message = new HttpMessage("Registration Request Sent", true);

                    string subject = "New DoeLibS account request";
                    string text = string.Format("<h3>New DoeLibs account request</h3><p>{0} {1} ({2}) asks of you to activate his account as a {3} member. Please visit your notification page in DoeLibS</p>", user.FirstName, user.LastName, user.EMail, user.Category.Name);
                    DoeObjects.MailManager.sendMail(user.Acceptor.EMail, subject, text);

                    return RedirectToAction("Login", "Authentification");
                }
                else
                {
                    base.Message = new HttpMessage("Technical problems during save. Please try again", false);
                }
			}
            
            return View(model);
		}

        /// <summary>
        /// controller to activate an account
        /// </summary>
        /// <param name="id">accountId</param>
        /// <param name="msgId">notoficationId (has to be deleted afterwards)</param>
        /// <returns></returns>
        [Authorize(Roles=UserCategoryHelper.STAFF_CATEGORY)]
        public bool ActivateAccount(int id, int msgId)
        {
            User userToActivate = DoeObjects.User.getUserByUserId(id);
            
            if(userToActivate != null)
            {
                if(userToActivate.Acceptor == null) 
                {
                    return true; //account already activated
                }
                else 
                {
                    Notification notification = null;
                    if (userToActivate.Acceptor.UserId == User.UserId && (notification = Notification.getById(msgId)) != null && notification.Recipient.UserId == User.UserId)
                    {
                        //this is the user who is supposed to activate this account
                        if(DoeObjects.User.activateUser(id) && Notification.delete(msgId)) 
                        {
                            //TODO: send message to user, account was activated...
                            DoeObjects.User.informActivatedUser(userToActivate.EMail);

                            return true;
                        }
                    }
                }
            }

            return false;
        }

        [Authorize(Roles=UserCategoryHelper.STAFF_CATEGORY)]
        public bool DenyAccount(int id, int msgId)
        {
            User userToActivate = DoeObjects.User.getUserByUserId(id);
            
            if(userToActivate != null)
            {
                if(userToActivate.Acceptor == null) 
                {
                    return true; //account already activated
                }
                else 
                {
                    Notification notification = null;
                    if(userToActivate.Acceptor.UserId == User.UserId && (notification = Notification.getById(msgId)) != null && notification.Recipient.UserId == User.UserId ) 
                    {
                        //this is the user who is supposed to activate this account
                        if(Notification.delete(msgId) && DoeObjects.User.delete(id))
                        {
                            //TODO: send message to user, account was not allowed...
                            DoeObjects.User.informDeneyedUser(userToActivate.EMail);

                            return true;
                        }
                    }
                }
            }

            return false;
        }
    }
}
